package socket

import (
	"encoding/json"
	"errors"
	"fmt"
	"github.com/Sir-yuChen/funAnalyse/global"
	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
	"github.com/gorilla/websocket"
	"go.uber.org/zap"
	"net/http"
	"strings"
	"time"
)

var (
	upgrader = websocket.Upgrader{
		// 读取存储空间大小
		ReadBufferSize: 1024,
		// 写入存储空间大小
		WriteBufferSize: 1024,
		// 允许跨域
		CheckOrigin: func(r *http.Request) bool {
			return true
		},
	}
)

// CreateWebSocketConnection 创建一个长链接
func CreateWebSocketConnection(customerId string, useMark string, ctx *gin.Context) error {
	Start()
	// 将http升级为websocket
	conn, err := (upgrader.Upgrade(ctx.Writer, ctx.Request, nil)) // 升级
	if err != nil {
		global.GVA_LOG.Error("创建websocket长链接异常", zap.Error(err), zap.Any("customerId", customerId))
		http.NotFound(ctx.Writer, ctx.Request)
		return errors.New("http升级为websocket异常")
	}
	// 创建一个实例连接
	uid, _ := uuid.NewUUID()
	ConnId := strings.Replace(uid.String(), "-", "", -1)
	client := &Client{
		ID:            ConnId, // 连接id
		CustomerId:    fmt.Sprintf("%s", customerId),
		HeartbeatTime: time.Now().Unix(),
		UseMark:       useMark,
		Socket:        conn,
	}
	// 用户注册到用户连接管理
	RegisterChan <- client
	go func() {
		// 读取信息
		defer func() {
			if r := recover(); r != nil {
				global.GVA_LOG.Error("CreateStockWeb read panic", zap.Any("Error", r), zap.Any("customerId", customerId))
			}
		}()
	}()
	client.Read()
	return nil
}

// CloseWebSocketConnection 关闭用户长链接
func CloseWebSocketConnection(customerId string) error {
	clients := GetClient(customerId)
	for _, client := range clients {
		// 注销用户长连接
		unregisterChan <- client
	}
	return nil
}

// 根据账号获取连接
func GetClient(customerId string) []*Client {
	clients := make([]*Client, 0)

	Manager.mu.Lock()
	defer Manager.mu.Unlock()
	_, ok := Manager.Accounts[customerId]
	if ok {
		for _, clientId := range Manager.Accounts[customerId] {
			if c, ok := Manager.Clients[clientId]; ok {
				clients = append(clients, c)
			}
		}
	}
	return clients
}

// 发送消息
func (c *Client) Send(message ServiceMessage) error {
	msg, err := json.Marshal(message)
	if err != nil {
		return err
	}
	c.Socket.WriteMessage(websocket.TextMessage, msg)
	return nil
}

// 读取信息，即收到消息
func (c *Client) Read() {
	defer func() {
		_ = c.Socket.Close()
	}()
	for {
		// 读取消息
		_, body, err := c.Socket.ReadMessage()
		if err != nil {
			break
		}
		var msg ServiceMessage
		err = json.Unmarshal(body, &msg)
		if err != nil {
			global.GVA_LOG.Error("socketwb 数据转换异常", zap.Any("CustomerId", c.CustomerId), zap.Any("body", string(body)), zap.Error(err))
			continue
		}
		global.GVA_LOG.Info("消息内容：", zap.Any("msg", msg))
		if msg.Type == MessageTypeHeartbeat { // 维持心跳消息
			// 刷新连接时间
			c.HeartbeatTime = time.Now().Unix()
			// 回复心跳
			replyMsg := CreateReplyMsg(MessageTypeHeartbeat, ServiceMessageContent{})
			err = c.Socket.WriteMessage(websocket.TextMessage, replyMsg)
			if err != nil {
				global.GVA_LOG.Error("socketwb 维持心跳异常", zap.Any("CustomerId", c.CustomerId), zap.Error(err))
			}
			continue
		}
		//todo 根据消息发送的消息找到对应的人

	}
}
func CreateReplyMsg(t string, content ServiceMessageContent) []byte {
	replyMsg := ServiceMessage{
		Type:    t,
		Content: content,
	}
	msg, _ := json.Marshal(replyMsg)
	return msg
}
